<?php
/**
 * @link https://www.kancloud.cn/cleverstone/ymb2
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

use yii\helpers\Json;
use builder\helper\Url;
use builder\helper\RegEx;
use builder\helper\App;

/* ====== 表单构建器 ====== */

/* @var \yii\web\View $this */
/** @var \builder\form\FormBuilder $context 当前表单组件实例 */
/** @var array $body 表单内容 */
/** @var array $bodyJsOptions 表单内容JS选项 */
/** @var bool $autoClose 是否提交后自动关闭表单 */
/** @var bool $autoBack 是否提交后自动返回 */
/** @var array $submitConfirm 设置表单提交确认框 */
/** @var array $submittedCalls 表单自动提交后的回调, 空数组代表不回调 */
/** @var array $extraJs 额外的JS脚本 */
/** @var array $formDynamicSelect 表单动态select */
/** @var array $formValueLink 表单值连接选项 */
/** @var array $formTrigger 表单触发器选项 */
/** @var array $formWatchScope 表单监听的字段模型 */
/** @var array $submittedRedirect 表单提交后重定向, 空数组代表无操作 */
/** @var array $formDynamicControl 表单动态控件选项 */

// 上下文对象
$context = $this->context;
?>
<script>
    void function (global, top) { "use strict";
        global.ym2App.controller("ym2.ctrl.<?= $context->id ?>", [
            "$scope",
            "$http",
            "ymSpinner",
            "layui",
            "ym2",
            "swal",
            "lodash",
            "ue",
            "Sortable",
            "$timeout",
            "$interval",
            "xmSelect",
            "tinyMCE",
            "jQuery",
            "$compile",
            function ($scope, $http, ymSpinner, layui, ym2, swal, lodash, ue, Sortable, $timeout, $interval, xmSelect, tinyMCE, jQuery, $compile) {
                // 提交URL
                var formBuilderId = "<?= $context->id ?>";
                var topSwal = top.swal;
                var topToastr = top.toastr;
                var topLayer = top.layui.layer;
                var topJquery = top.jQuery;
                var topYmSpinner = top.ymSpinner;
                var formSubmitUrl = "<?= $context->submitUrl ?>";
                var bodyJsOptions = <?= Json::encode($bodyJsOptions) ?>;
                var submittedCalls = <?= Json::encode($submittedCalls) ?>;
                var submittedRedirectOptions = <?= Json::encode($submittedRedirect) ?>;
                var formDynamicSelect = <?= Json::encode($formDynamicSelect) ?>;
                var HTTP_SUCCESS_CODE = <?= App::params('http.res.success') ?>;
                var HTTP_FAILURE_CODE = <?= App::params('http.res.failure') ?>;
                var HTTP_UNAUTHORITY_CODE = <?= App::params('http.res.unauthorized') ?>;
                var ADMIN_LOGIN_URL = '<?= Url::to(App::params('admin.route.login'), '') ?>';
                var dialog_dump_login_page = function (msg) {
                    ym2.swal.timer(
                        topSwal,
                        msg,
                        "自动跳转; <a href='"+ADMIN_LOGIN_URL+"' target='_top'>立即跳转<a/>",
                        function () {
                            top.open(ADMIN_LOGIN_URL, "_self");
                        },
                        3000
                    );
                };

                //编译HTML字符串
                $scope.$compileHtml = function (v) {
                    // 参数值显式转为字符串类型
                    v = String(v);
                    var htmlTokenCount = 0;
                    try {
                        //参数值为Text时，jQuery不解析。
                        htmlTokenCount = jQuery( v ).length;
                    } catch (e) {
                        console.log('html解析失败判断为text：' + v);
                    }
                    return htmlTokenCount > 0 ? $compile( v )( $scope ) : v;
                };

                // 关闭表单弹窗
                $scope.formClose = function () {
                    var layerIndex = topLayer.getFrameIndex(global.name);
                    layerIndex !== void 0 && layerIndex !== null && topLayer.close(layerIndex);

                    return true;
                };

                // 返回上一页
                $scope.formBack = function () {
                    global.history.go(-1);
                    return true;
                };

                // 表单重置
                var tinyMCE_Init_Content = {};
                $scope.formReset = function (event, isInit) {
                    isInit = isInit || false;
                    var ueEditor;
                    var formOptions;
                    var xselectOptions;
<?php foreach ($body as $groupField => $options): ?>
                    // ======================================= 表单组<?= $groupField ?>定义 =======================================
                    formOptions = bodyJsOptions["<?= $groupField ?>"];
                    $scope["<?= $groupField ?>"] = {};
                    <?= RegEx::js($this->renderPhpFile(__DIR__ . '/tpl/app.form.init.php', [
                        'controlItems' => $options['controls'],
                        'groupField' => $groupField,
                    ])) ?>
<?php endforeach; ?>
                };

                // 获取表单内容
                $scope.getYm2FormContent = function () {
                    // UE
                    var ueEditor;
                    // 当前分组字段
                    var currentGroupField;
                    // 输出结果
                    var result = {};
                    // 动态控件中不提交字段
                    var dynamicUnSubmitFields = [];

<?php foreach ($body as $groupField => $options): ?>
                    // ======================================= 表单组<?= $groupField ?>内容提交 =======================================

                    currentGroupField = "<?= $groupField ?>";
                    result[currentGroupField] = {};
                    // 表单控件值获取JS脚本
                    <?= RegEx::js($this->renderPhpFile(__DIR__ . '/tpl/app.form.get.php', [
                        'controlItems' => $options['controls'],
                    ])) ?>
<?php endforeach; ?>
                    return result;
                };

                // 表单提交事件
                $scope.formSubmit = function () {
                    var isConfirm = <?= (int)$submitConfirm['show'] ?>;
                    if (!isConfirm) {
                        $scope.runSubmitRequest();
                    } else {
                        ym2.swal.question(
                            topSwal,
                            "<?= $submitConfirm['title'] ?>",
                            "<?= $submitConfirm['content'] ?>",
                            function (result) {
                                //确认提交
                                if (result.isConfirmed) {
                                    $scope.$apply(function () {
                                        $scope.runSubmitRequest();
                                    });
                                }
                            });
                    }
                };
                // 表单值校验
                $scope._actionFormValidation = function() {
                    var formData = $scope.getYm2FormContent();
                    var keyLen = ym2.keys(formData).length;
                    var __isPass = true;

                    // 表单为空检查
                    if (__isPass) {
                        if (keyLen <= 0) {
                            topToastr.warning("请填写表单");
                            __isPass = false;
                        }
                    }

                    // 普通控件校验
                    if (__isPass) {
                        Loop0:for (var groupField in formData) {
                            var validatorGroups = bodyJsOptions[groupField];
                            if (!validatorGroups) {
                                continue;
                            }

                            var cFormGroup = formData[groupField];
                            for (var field in cFormGroup) {
                                if (!validatorGroups[field]) {
                                    continue;
                                }

                                var validatorOpt = validatorGroups[field];
                                var itemIsEmpty = ym2.isEmpty(cFormGroup[field]);
                                //必填校验
                                if (itemIsEmpty && validatorOpt['required'] && (!validatorOpt['requiredWhere'] || eval(validatorOpt['requiredWhere']))) {
                                    /** 必填条件为空或者必填条件结果是真 */
                                    topToastr.warning((validatorGroups[field]['label'] || field) + "不能为空。");
                                    __isPass = false;
                                    break Loop0;
                                }

                                //规则校验
                                if (!itemIsEmpty && validatorOpt['regexp'] && !ym2.strToRegexp(validatorOpt['regexp']).test(cFormGroup[field])) {
                                    console.log(field + '校验正则：', ym2.strToRegexp(validatorOpt['regexp']));
                                    topToastr.warning((validatorGroups[field]['label'] || field) + "不符合匹配规则。");
                                    __isPass = false;
                                    break Loop0;
                                }
                            }
                        }
                    }

<?php if (!empty($formDynamicControl)): ?>
                    // 动态控件校验
                    <?= RegEx::js($this->renderPhpFile(__DIR__ . '/tpl/app.dynamic.control.validate.php', ['formDynamicControl' => $formDynamicControl])) ?>
<?php endif; ?>

                    // 返回结果
                    if (!__isPass) { return false; }
                    if (keyLen <= 1) {
                        formData = Object.keys(formData).map(function (i) {
                            return formData[i];
                        })[0];
                    }

                    return formData;
                };
                // 发起提交请求
                $scope.runSubmitRequest = function () {
                    // 获取表单数据
                    var formData = $scope._actionFormValidation();
                    if (formData === false) { return; }

                    // 发起请求
                    var flag = ymSpinner.show();
                    $http.post(formSubmitUrl, formData).then(function (result) {
                        ymSpinner.hide(flag);
                        var data = result.data;
                        switch (data.code) {
                            case HTTP_SUCCESS_CODE: //业务成功
                                // 成功轻提示
                                if (data.msg) {
                                    topToastr.success(data.msg);
                                }

                                // 执行Successful回调
                                $scope._actionSubmittedCallback("successCallback");

                                // 表单提交后重定向,空数组代表无操作
                                $scope._actionSubmittedRedirect(data.data || []);

<?php if ($autoClose): ?>
                                // 自动关闭弹窗
                                var layerIndex = topLayer.getFrameIndex(global.name);
                                layerIndex !== void 0 && layerIndex !== null && topLayer.close(layerIndex);
<?php elseif ($autoBack): ?>
                                // 自动返回上一页
                                global.history.go(-1);
<?php endif; ?>

                                break;
                            case HTTP_FAILURE_CODE: //业务失败
                                topToastr.error(data.msg);
                                // 执行Failure回调
                                $scope._actionSubmittedCallback("failureCallback");

                                break;
                            case HTTP_UNAUTHORITY_CODE://授权失效, 去登录
                                // 授权失效, 去登录
                                dialog_dump_login_page(data.msg);

                                break;
                            default://其他
                                topToastr.error(data.msg);
                        }

                    }, function (error) {
                        ymSpinner.hide(flag);
                        topToastr.error(error.data || "系统错误, 发起请求失败!");
                        global.console.error(error);
                    });
                };
                //表单提交后重定向,空数组代表无操作
                $scope._actionSubmittedRedirect = function (data) {
                    var L = Object.keys(submittedRedirectOptions).length;
                    if (L <= 0) {
                        return;
                    }

                    var type = submittedRedirectOptions.type;
                    var url = submittedRedirectOptions.route;
                    var params = submittedRedirectOptions.params || [];

                    if (ym2.keys(params).length) {
                        params = ym2.fillParams(params, data);
                        url = ym2.addUrlQueryParam(url, params);
                    }

                    switch (type) {
                        case "modal"://modal
                            // layer动态唯一索引
                            var activeIndex = topLayer.index;
                            // modal title
                            var title = submittedRedirectOptions.title || '';
                            // modal width
                            var width = submittedRedirectOptions.width || "100%";
                            // modal height
                            var height = submittedRedirectOptions.height || "100%";
                            // modal footer close btn
                            var footerCloseBtn = submittedRedirectOptions.closeBtn;
                            // layer screen obj
                            var layerScreenObj = ym2.layerScreenOptions(width);
                            var refererName = ym2.layerRefererWindowName( submittedRedirectOptions.refererWindow );

                            // var loadingFlag = topYmSpinner.show("加载中...");
                            // iframe 模态框
                            var layerCf = {
                                type: 2, // iframe
                                //skin: 'layui-layer-win10',
                                area: [layerScreenObj.width, height],
                                title: title,
                                shade: 0.3, // 遮罩透明度
                                shadeClose: false, // 点击遮罩区域，关闭弹层
                                closeBtn: submittedRedirectOptions.titleCloseBtn,
                                maxmin: submittedRedirectOptions.titleMaxminBtn,// 允许全屏最小化
                                anim: 0, // 0-6 的动画形式，-1 不开启
                                scrollbar: false, // 打开弹层时，是否允许浏览器出现滚动条。
                                content: url,
                                success: function(layero, index, that){
                                    // topYmSpinner.hide( loadingFlag );
                                    // 弹层的最外层元素的 jQuery 对象
                                    //console.log(layero);
                                    // 弹层的索引值
                                    //console.log(index);
                                    // 弹层内部原型链中的 this --- 2.8+
                                    //console.log(that);
                                    // 获取iframe的窗口对象, 添加来源追踪
                                    var iframeWin = top[layero.find("iframe")[0]["name"]];
                                    iframeWin.__REFERER_WIN_NAME = refererName;
                                    //键盘事件关闭
                                    topJquery(".ym2_kc_" + activeIndex).focus().on("keydown", function (e) {
                                        // 空格和回车键
                                        if (e.keyCode === 13 || e.keyCode === 32) {
                                            topJquery(this).trigger("click");
                                        }
                                    });
                                },
                            };
                            if (footerCloseBtn) {
                                layerCf.btn = ['<span class="ym2_keydown_close ym2_kc_' + activeIndex + '" tabindex="0">关闭</span>'];
                            }

                            topLayer.open(layerCf);
                            break;
                        case "page"://page
                            var target = submittedRedirectOptions.target;
                            var owin;
                            eval("owin = " + submittedRedirectOptions.window);
                            owin.open(url, target);

                            break;
                    }
                };
                /**
                 * 提交后回调
                 * @param {String} callbackName "successCallback"、"failureCallback"
                 * @private
                 */
                $scope._actionSubmittedCallback = function ( callbackName ) {
                    callbackName = callbackName || "successCallback";
                    var callbacks = submittedCalls[ callbackName ] || [],
                        callbackWindows = Object.keys( callbacks );
                    if ( callbackWindows.length <= 0 ) {
                        return;
                    }

                    callbackWindows.forEach(function (key) {
                        var callbackMethod = callbacks[ key ];
                        if ( key === "self" ) { //self
                            var selfCbkExport = global.ym2CbkExport || {};
                            if (!callbackMethod.length) {
                                // 回调所有
                                Object.keys(selfCbkExport).forEach(function (key) {
                                    /* $scope 当前表单域 */
                                    selfCbkExport[key].call();
                                });
                            } else {
                                // 指定回调
                                Object.keys(selfCbkExport).forEach(function (key) {
                                    if (lodash.indexOf(callbackMethod, key) !== -1) {
                                        /* $scope 当前表单域 */
                                        selfCbkExport[key].call();
                                    }
                                });
                            }
                        } else if ( key.substring(0, 6) === "parent" && global !== global.parent ) {//parent.parent*
                            var keysMap = key.split('.');
                            var currentWin = global;
                            var refererWinName = currentWin.__REFERER_WIN_NAME;

                            var parentWin;
                            for (var i = 0; i < keysMap.length; i++) {
                                parentWin = refererWinName ? top[refererWinName] : currentWin.parent;
                                currentWin = parentWin;
                                refererWinName = parentWin.__REFERER_WIN_NAME;
                            }

                            var parentCbkExport = parentWin.ym2CbkExport || {};
                            if (!callbackMethod.length) {
                                // 回调所有
                                Object.keys(parentCbkExport).forEach(function (key) {
                                    /* $scope 当前表单域 */
                                    parentCbkExport[key].call();
                                });
                            } else {
                                // 指定回调
                                Object.keys(parentCbkExport).forEach(function (key) {
                                    if (lodash.indexOf(callbackMethod, key) !== -1) {
                                        /* $scope 当前表单域 */
                                        parentCbkExport[key].call();
                                    }
                                });
                            }
                        } else {
                            //...
                            console.warn(key + " No callback. ");
                        }

                    });
                };

                // 动态控件事件脚本
<?php if (!empty($formDynamicControl)): ?>
                <?= RegEx::js($this->renderPhpFile(__DIR__ . '/tpl/app.dynamic.control.action.php', [
                    'formDynamicControl' => $formDynamicControl,
                ])) ?>
<?php endif; ?>
                // 动态下拉控件 - 刷新
                $scope.actionDynamicSelectRefresh = function (controlId) {
                    formDynamicSelect.forEach(function (value, index, array) {
                        if ( controlId === value.__id ) {
                            $scope._actionInitDs(value);
                        }
                    });
                };
                $scope._actionInitDs = function ( config ) {
                    // show loading
                    var flag = ymSpinner.show();
                    $http.get( config.optionUrl ).then(function (result) {
                        ymSpinner.hide(flag);

                        var data = result.data;
                        switch (data.code) {
                            case HTTP_SUCCESS_CODE:
                                $scope[config.__id + '__item_options'] = data.data;

                                break;
                            case HTTP_FAILURE_CODE:
                                topToastr.error(data.msg);

                                break;
                            case HTTP_UNAUTHORITY_CODE:
                                // 授权失效, 去登录
                                dialog_dump_login_page(data.msg);

                                break;
                            default:
                                topToastr.error(data.msg);
                        }
                    }, function (error) {
                        ymSpinner.hide(flag);
                        topToastr.error(error.data || "系统错误, 发起请求失败!");
                        global.console.error(error);
                    });
                };

                // 动态下拉控件 - 新增
                $scope.actionDynamicSelectAdd = function (controlId) {
                    var openOption;
                    formDynamicSelect.forEach(function (value, index, array) {
                        if (controlId === value.__id) {
                            openOption = value.additionBtn;

                            switch (openOption.type) {
                                case "modal": //模态框
                                    // layer动态唯一索引
                                    var activeIndex = topLayer.index;
                                    // modal title
                                    var title = openOption.title || '';
                                    // modal width
                                    var width = openOption.width || "100%";
                                    // modal height
                                    var height = openOption.height || "100%";
                                    // modal footer close btn
                                    var footerCloseBtn = openOption.closeBtn;
                                    // layer screen obj
                                    var layerScreenObj = ym2.layerScreenOptions(width);
                                    var url = ym2.addUrlQueryParam(openOption.route, {
                                        __callId : value.__id,
                                    });

                                    // 挂载回调
                                    global.ym2CbkExport[value.__id] = function () {
                                        $scope.$apply(function () {
                                            $scope.actionDynamicSelectRefresh(value.__id);
                                        });
                                    };

                                    var refererName = ym2.layerRefererWindowName( openOption.refererWindow );
                                    // var loadingFlag = topYmSpinner.show("加载中...");
                                    // iframe 模态框
                                    var layerCf = {
                                        type: 2, // iframe
                                        //skin: 'layui-layer-win10',
                                        area: [layerScreenObj.width, height],
                                        title: title,
                                        shade: 0.3, // 遮罩透明度
                                        shadeClose: false, // 点击遮罩区域，关闭弹层
                                        closeBtn: openOption.titleCloseBtn,
                                        maxmin: openOption.titleMaxminBtn, // 允许全屏最小化
                                        anim: 0, // 0-6 的动画形式，-1 不开启
                                        scrollbar: false, // 打开弹层时，是否允许浏览器出现滚动条。
                                        content: url,
                                        success: function(layero, index, that){
                                            // topYmSpinner.hide( loadingFlag );
                                            // 弹层的最外层元素的 jQuery 对象
                                            //console.log(layero);
                                            // 弹层的索引值
                                            //console.log(index);
                                            // 弹层内部原型链中的 this --- 2.8+
                                            //console.log(that);
                                            // 获取iframe的窗口对象, 添加来源追踪
                                            var iframeWin = top[layero.find("iframe")[0]["name"]];
                                            iframeWin.__REFERER_WIN_NAME = refererName;
                                            //键盘事件关闭
                                            topJquery(".ym2_kc_" + activeIndex).focus().on("keydown", function (e) {
                                                // 空格和回车键
                                                if (e.keyCode === 13 || e.keyCode === 32) {
                                                    topJquery(this).trigger("click");
                                                }
                                            });
                                        },
                                    };
                                    if (footerCloseBtn) {
                                        layerCf.btn = ['<span class="ym2_keydown_close ym2_kc_' + activeIndex + '" tabindex="0">关闭</span>'];
                                    }

                                    topLayer.open(layerCf);

                                    break;
                                case "page": //单页
                                    var target = openOption.target;
                                    var owin;
                                    eval("owin = " + openOption.window);
                                    owin.open(openOption.route, target);

                                    break;
                            }
                        }
                    });
                };

                // 下拉联动监听
                $scope.callSelectLink = function (group, field, target, url) {
                    var currentValue = $scope[group][field];
                    var targetGroup = target.group;
                    var targetField = target.field;
                    var queryParams = {};
                    var emptyValue = "\t\r\n";

                    // 空值处理
                    if (!currentValue || !lodash.trim(currentValue)) {
                        // 初始化目标连接的值
                        $scope[targetGroup][targetField] = emptyValue;
                        // 初始化目标连接选项
                        $scope[targetGroup + '__' + targetField + '__options'] = [];
                        return;
                    }

                    queryParams[field] = currentValue;
                    // show loading
                    var flag = ymSpinner.show();
                    $http.get(ym2.addUrlQueryParam(url, queryParams)).then(function (result) {
                        ymSpinner.hide(flag);

                        var data = result.data;
                        switch (data.code) {
                            case HTTP_SUCCESS_CODE:
                                // 设置目标连接选项
                                $scope[targetGroup + '__' + targetField + '__options'] = data.data || [];
                                Promise.resolve(true).then(function () {
                                    // 初始化目标连接的值
                                    $scope[targetGroup][targetField] = emptyValue;
                                });

                                break;
                            case HTTP_FAILURE_CODE:
                                topToastr.error(data.msg);

                                break;
                            case HTTP_UNAUTHORITY_CODE:
                                // 授权失效, 去登录
                                dialog_dump_login_page(data.msg);

                                break;
                            default:
                                topToastr.error(data.msg);
                        }

                    }, function (error) {
                        ymSpinner.hide(flag);
                        topToastr.error(error.data || "系统错误, 发起请求失败!");
                        global.console.error(error);
                    });
                };

                // 表单数据模型监听
<?php foreach ($formWatchScope as $index => $value): ?>
                var timer<?= $index ?>;
                $scope.$watch("<?= $value ?>", function (newVal, oldVal) {
                    // 表单触发器脚本
<?php foreach ($formTrigger as $item): ?>
<?php if (in_array($value, $item['watchScope'])): ?>
                    $scope.<?= $item['__scope'] ?> = <?= $item['where'] ?>;
<?php if (!empty($item['whereIsTrueJsCbk'])): ?>
                    // 表单触发器 - 触发条件为 true 时，后台自定义js回调触发
                    try {
                        if ( $scope.<?= $item['__scope'] ?> ) {
                            (function () {
                                <?= $item['whereIsTrueJsCbk'] ?>

                            }());
                        }
                    } catch (exception) {
                        console.warn('触发条件为 true 时，后台自定义js回调执行错误：', exception);
                    }
<?php endif; ?>
<?php if (!empty($item['whereIsFalseJsCbk'])): ?>
                    // 表单触发器 - 触发条件为 false 时，后台自定义js回调触发
                    try {
                        if ( !$scope.<?= $item['__scope'] ?> ) {
                            (function () {
                                <?= $item['whereIsFalseJsCbk'] ?>

                            }());
                        }
                    } catch (exception) {
                        console.warn('触发条件为 false 时，后台自定义js回调执行错误：', exception);
                    }
<?php endif; ?>
<?php endif; ?>
<?php endforeach; ?>

                    // 表单值连接脚本
                    if (newVal !== oldVal) {
<?php foreach ($formValueLink as $item): ?>
<?php if (in_array($value, $item['watchScope'])): ?>
                        var params = {
<?php foreach ($item['sourceControl'] as $field => $vv): ?>
                            "<?= $field ?>": $scope.<?= $vv['__scope'] ?>,
<?php endforeach; ?>
                        };
                        if (timer<?= $index ?>) {
                            $timeout.cancel(timer<?= $index ?>);
                        }

                        timer<?= $index ?> = $timeout(function () {
                            $scope._actionVlinkRequest("<?= $item['targetRoute'] ?>", params, function (data) {
                                $scope.<?= $item['__targetScope'] ?> = data;
                            });
                        }, 250);
<?php endif; ?>
<?php endforeach; ?>
                    }

                }, true);
<?php endforeach; ?>

                // 值连接HTTP请求
                $scope._actionVlinkRequest = function (url, params, successCallback) {
                    //发起请求
                    $http.post(url, params).then(function (result) {

                        var data = result.data;
                        switch (data.code) {
                            case HTTP_SUCCESS_CODE:
                                successCallback(data.data);

                                break;
                            case HTTP_FAILURE_CODE:
                                topToastr.error(data.msg || '结果无法识别');

                                break;
                            case HTTP_UNAUTHORITY_CODE:
                                // 授权失效, 去登录
                                dialog_dump_login_page(data.msg);

                                break;
                            default:
                                topToastr.error(data.msg || '结果无法识别');
                        }

                    }, function (error) {
                        topToastr.error(error.data || "系统错误, 发起请求失败!");
                        global.console.error(error);
                    });
                };

                // 表单控件Range步进器事件(mousedown) +
                var TimerHandle = null;
                var TimeInterval = 130;
                $scope.triggerIncreaseStep = function ( group, field, step, max ) {
                    if ( TimerHandle !== null ) return;
                    var current = parseFloat( $scope[ group ][ field ] );
                    var callback = function () {
                        if ( current < max ) {
                            current += step;
                            if ( current >= max ) current = max;
                            $scope[ group ][ field ] = current;
                        }
                    };
                    callback();
                    TimerHandle = $interval( function () {
                        callback();
                    }, TimeInterval );
                };
                // 表单控件Range步进器事件(mousedown) -
                $scope.triggerDecreaseStep = function ( group, field, step, min ) {
                    if ( TimerHandle !== null ) return;
                    var current = parseFloat( $scope[ group ][ field ] );
                    var callback = function () {
                        if ( current > min ) {
                            current -= step;
                            if ( current <= min ) current = min;
                            $scope[ group ][ field ] = current;
                        }
                    };
                    callback();
                    TimerHandle = $interval( function () {
                        callback();
                    }, TimeInterval );
                };
                //表单控件Range步进器事件(mouseup) cancel timer
                $scope.cancelStepperTimer = function () {
                    if ( TimerHandle !== null ) {
                        $interval.cancel( TimerHandle );
                        TimerHandle = null;
                    }
                };

                //下拉选择表格，model改变时触发。
                $scope.actionSelectTable = function (option) {
                    var title = option.title;
                    var width = option.width;
                    var height = option.height;
                    //自适应modal尺寸
                    var layerScreenObj = ym2.layerScreenOptions( width );
                    var url = option.route;
                    var s = {};

                    jQuery.each( option.dynamicParams, function (i , v) {
                        s[ i ] = $scope.$eval( v );
                    });

                    //iframe 模态框
                    var refererName = ym2.layerRefererWindowName( option.refererWindow );
                    var iframeWin;
                    // var loadingFlag = topYmSpinner.show("加载中...");
                    var layerCf = {
                        type: 2, // iframe
                        //skin: 'layui-layer-win10',
                        area: [layerScreenObj.width, height],
                        title: title,
                        shade: 0.3, // 遮罩透明度
                        shadeClose: false, // 点击遮罩区域，关闭弹层
                        closeBtn: option.titleCloseBtn,
                        maxmin: option.titleMaxminBtn, // 允许全屏最小化
                        anim: 0, // 0-6 的动画形式，-1 不开启
                        scrollbar: false, // 打开弹层时，是否允许浏览器出现滚动条。
                        content: ym2.addUrlQueryParam( url, s ),
                        btn: ["确认选择"],
                        success: function(layero, index, that){
                            // topYmSpinner.hide( loadingFlag );
                            // 弹层的最外层元素的 jQuery 对象
                            //console.log(layero);
                            // 弹层的索引值
                            //console.log(index);
                            // 弹层内部原型链中的 this --- 2.8+
                            //console.log(that);
                            // 获取iframe的窗口对象, 添加来源追踪
                            iframeWin = top[ layero.find("iframe")[0]["name"] ];
                            iframeWin.__REFERER_WIN_NAME = refererName;
                        },
                        btn1: function (index, layero, that) {
                            if ( !iframeWin || !iframeWin.ym2PageDataExport ) {
                                topToastr.error("请检查是否设置了模态框路由或是否挂载了【window.ym2PageDataExport】。");
                                return;
                            }

                            var checkedState = iframeWin.ym2PageDataExport[ option.callId ]();
                            var selectedData = checkedState.data;
                            // var isSelectedAll = checkedState.isAll;
                            if ( !selectedData.length ) {
                                topToastr.info("请选择数据项");
                                return;
                            }

                            var normalizeData = [];
                            selectedData.forEach(function ( value ) {
                                var tmpObj = {};
                                tmpObj[ option.nameField ] = value[ option.nameField ];
                                tmpObj[ option.valueField ] = value[ option.valueField ];
                                normalizeData.push(tmpObj);
                            });

                            //广播函数
                            var $digestFunc;
                            if ( option.repeat ) {
                                $digestFunc = function () {
                                    $scope[ option.groupField ][ option.field ] = lodash.concat( $scope[ option.groupField ][ option.field ], normalizeData );
                                };
                            } else {
                                var intersection = lodash.intersectionBy( $scope[ option.groupField ][ option.field ], normalizeData, option.valueField );
                                if ( intersection.length && option.tipOnRepeat ) {
                                    topToastr.info("选择项存在重复，请检查后重新选择。");
                                    return;
                                }

                                $digestFunc = function () {
                                    $scope[ option.groupField ][ option.field ] = lodash.unionBy(
                                        $scope[ option.groupField ][ option.field ],
                                        normalizeData,
                                        option.valueField,
                                    );
                                };
                            }

                            $scope.$apply($digestFunc);

                            if ( option.closeOnSelected ) {
                                topLayer.close( index );
                            }
                        },
                    };
                    topLayer.open(layerCf);

                };

                //表单控件-动态标签-远程功能
                jQuery(".ym-tag[lay-filter]").each(function ( index, element ) {
                    var _Tag =  layui.ym2FormTag,
                        _filter = element.getAttribute("lay-filter");

                    _Tag.on("remote(" + _filter + ")", function ( object ) {
                        var tagRootElement = object.elem,
                            option = tagRootElement.data( "config" ),
                            allowMaxCount = object.elem.attr( "lay-maxcount" ) || 9999,
                            title = option.title,
                            width = option.width,
                            height = option.height,
                            layerScreenObj = ym2.layerScreenOptions( width ),
                            url = option.route,
                            iframeWin,//iFrame 模态框
                            // loadingFlag = topYmSpinner.show("加载中..."),
                            refererName = ym2.layerRefererWindowName( option.refererWindow ),
                            layerCf = {
                            type: 2,//iFrame
                            area: [ layerScreenObj.width, height ],
                            title: title,
                            shade: 0.3,//遮罩透明度
                            shadeClose: false,//点击遮罩区域，关闭弹层
                            closeBtn: option.titleCloseBtn,
                            maxmin: option.titleMaxminBtn, // 允许全屏最小化
                            anim: 0,//0-6 的动画形式，-1 不开启
                            scrollbar: false,//打开弹层时，是否允许浏览器出现滚动条。
                            content: url,
                            btn: ["确认选择"],
                            success: function(layero, index, that){
                                // topYmSpinner.hide( loadingFlag );
                                // 获取iFrame的窗口对象, 添加来源追踪
                                iframeWin = top[ layero.find("iframe")[0]["name"] ];
                                iframeWin.__REFERER_WIN_NAME = refererName;
                            },
                            btn1: function (index, layero, that) {
                                if ( !iframeWin || !iframeWin.ym2PageDataExport ) {
                                    topToastr.error("请检查是否设置了模态框路由或是否挂载了【window.ym2PageDataExport】。");
                                    return;
                                }

                                var checkedState = iframeWin.ym2PageDataExport[ option.callId ]();
                                var selectedData = checkedState.data;
                                // var isSelectedAll = checkedState.isAll;
                                if ( !selectedData.length ) {
                                    topToastr.info("请选择数据项");
                                    return;
                                }

                                for (var i in selectedData) {
                                    var tmpObj = {};
                                    tmpObj[ "text" ] = selectedData[ i ][ option.textField ];
                                    //标签数量超出max 或 新增标签失败，break for loop；
                                    if ( _Tag.values( _filter ).length >= allowMaxCount || false === _Tag.add( _filter, tmpObj ) ) {
                                        break;
                                    }
                                }

                                if ( option.closeOnSelected ) {
                                    topLayer.close( index );
                                }
                            },
                        };

                        topLayer.open(layerCf);

                    });

                });

                //额外的JS脚本
                <?= !empty($extraJs) ? implode("\n", $extraJs) : '' ?>

                // 初始化表单
                $scope.formReset(null, true);

                // 暴露表单数据，用于分步表单构建器
                global.ym2PageDataExport[formBuilderId] = $scope._actionFormValidation;

            }]);
    }(window, top);
</script>
